package com.mzj.saas.mservice.smartlock.service.ruanku;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mzj.saas.commons.enums.BacklogItemTypeEnum;
import com.mzj.saas.commons.enums.LockAlarmTypeEnum;
import com.mzj.saas.mservice.backlog.entity.BacklogItem;
import com.mzj.saas.mservice.backlog.entity.BacklogItemBattery;
import com.mzj.saas.mservice.backlog.entity.BacklogItemLockOff;
import com.mzj.saas.mservice.backlog.repository.BacklogItemBatteryRepository;
import com.mzj.saas.mservice.backlog.repository.BacklogItemLockOffRepository;
import com.mzj.saas.mservice.backlog.repository.BacklogItemRepository;
import com.mzj.saas.mservice.lock.Repository.LockAlarmRepository;
import com.mzj.saas.mservice.lock.Repository.LockOpenLogRepository;
import com.mzj.saas.mservice.lock.Repository.SmartLockPwdRepository;
import com.mzj.saas.mservice.lock.Repository.SmartLockRepository;
import com.mzj.saas.mservice.lock.entity.LockAlarm;
import com.mzj.saas.mservice.lock.entity.LockOpenLog;
import com.mzj.saas.mservice.lock.entity.SmartLock;
import com.mzj.saas.mservice.lock.entity.SmartLockPwd;
import com.mzj.saas.mservice.lockManager.entity.LockHouseSetting;
import com.mzj.saas.mservice.lockManager.repository.LockHouseSettingRepository;
import com.mzj.saas.mservice.property.entity.CommunityHouseUser;
import com.mzj.saas.mservice.property.repository.CommunityHouseUserRepository;
import com.mzj.saas.mservice.smartlock.sgin.LockUtils;
import com.mzj.saas.mservice.smartlock.vo.LockCallBackVO;
import com.mzj.saas.mservice.smartlock.vo.OpenRecordVO;
import com.mzj.saas.mservice.sys.entity.AppUser;
import com.mzj.saas.mservice.sys.repository.AppUserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 软库-智能锁事件处理
 * 
 * @author hp
 *
 */
@Service
public class LockEventHandleService {

	private static final Logger log = LoggerFactory.getLogger(LockEventHandleService.class);

	private static final String authSql = "SELECT a.id AS lockAuthId,a.author_user_id as userId,a.user_name as userName  FROM saas_smart_lock_auth a "
			+ "LEFT  JOIN  saas_smart_lock_pwd p ON a.id = p.lock_auth_id \n"
			+ "WHERE  a.lock_id = ? AND p.pwd_index  = ?";

	private static final String cardSql = "SELECT a.id AS lockAuthId,a.author_user_id as userId,a.user_name AS userName FROM saas_smart_lock_auth a LEFT JOIN "
			+ "saas_smart_lock_card c ON a.id = c.lock_auth_id WHERE a.lock_id = ? AND c.card_index = ?";

	@Autowired
	private JdbcTemplate jdbcTemplate;
	@Autowired
	private SmartLockRepository smartLockRepository;
	@Autowired
	private LockOpenLogRepository lockOpenLogRepository;
	@Autowired
	private SmartLockPwdRepository smartLockPwdRepository;
	@Autowired
	private BacklogItemRepository backlogItemRepository;
	@Autowired
	private BacklogItemBatteryRepository backlogItemBatteryRepository;
	@Autowired
	private BacklogItemLockOffRepository backlogItemLockOffRepository;
	@Autowired
	private LockHouseSettingRepository lockHouseSettingRepository;
	@Autowired
	private LockAlarmRepository lockAlarmRepository;
	@Autowired
	private AppUserRepository appUserRepository;
	@Autowired
	private CommunityHouseUserRepository communityHouseUserRepository;

	/**
	 * 锁离线事件
	 *
	 */
	public void lockOfflineCallBack(LockCallBackVO vo) {
		log.info("智能锁事件推送处理-->锁离线事件 vo={}", vo.toString());
		try {

			JSONArray array = JSONArray.parseArray(LockUtils.toString(vo.getResult()));

			if (array == null || array.isEmpty() || array.size() == 0) {
				log.warn("智能锁事件推送处理-->锁离线事件 result is null ={}", vo.getResult());
				return;
			}

			List<String> snList = new ArrayList<>();
			array.forEach(a -> {
				JSONObject jo = JSONObject.parseObject(a.toString());
				snList.add(jo.getString("sn"));
			});

			if (CollectionUtils.isEmpty(snList)) {
				log.warn("智能锁事件推送处理-->锁离线事件,result未找到设备");
				return;
			}

			List<SmartLock> lockList = smartLockRepository.findBySnIn(snList);

			if (CollectionUtils.isEmpty(lockList)) {
				log.warn("智能锁事件推送处理-->锁离线事件,数据库未找到设备信息");
				return;
			}

			lockList.forEach(l -> l.setOnlineStatus(0));

			smartLockRepository.saveAll(lockList);

			Date date = new Date();
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
			String today = formatter.format(date);
			lockList.forEach(l -> {

				BacklogItem log = backlogItemRepository.findByHouseIdAndType(l.getHouseId(),
						BacklogItemTypeEnum.LOCK_UNLINE.getValue(), today);

				if (log != null) {
					return;
				}

				String content = l.getCommunityName() + l.getUnitName() + l.getBuildName() + l.getRoomNumber();
				BacklogItem item = new BacklogItem();
				item.setHouseId(l.getHouseId());
				item.setOrgId(l.getOrgId());
				item.setTitle("门锁离线告警");
				item.setContent(content);
				item.setBusinessStatus("门锁离线量告警");
				item.setType(BacklogItemTypeEnum.LOCK_UNLINE.getValue());
				item.setHandleStatus(0);
				item.setMatchUserId(l.getMatchUserId());
				if (!StringUtils.isEmpty(l.getMatchUserId())){
					AppUser appUsers = appUserRepository.findByIdOrEnterpriseUserId(l.getMatchUserId(), l.getMatchUserId());
					if (appUsers != null ){
						item.setPhone(appUsers.getPhone());
					}

				}else {
					List<CommunityHouseUser> communityHouseUserList = communityHouseUserRepository.findByCommunityHouseIdAndStatusAndType(l.getHouseId(), 1, 1);
					if (communityHouseUserList != null && communityHouseUserList.size() > 0) {
						item.setMatchUserId(communityHouseUserList.get(0).getUserId());//承租人ID
						item.setPhone(communityHouseUserList.get(0).getMobile());//电话
					}
				}
				item.setCreateTime(date);
				backlogItemRepository.save(item);

				BacklogItemLockOff lockoff = new BacklogItemLockOff();
				lockoff.setBacklogItemId(item.getId());
				lockoff.setLockId(l.getId());
				lockoff.setMatchUserId(l.getMatchUserId());
				backlogItemLockOffRepository.save(lockoff);
			});

		} catch (Exception e) {
			log.error("锁离线事件处理异常" + e.getMessage(), e);
		}
	}

	/**
     * 锁开门事件
     * @param vo
     */
    public void openRecordCallBack(LockCallBackVO vo) {
    	log.info("智能锁事件推送处理-->锁开门事件 vo={}",vo.toString());
    	try {
    		
            JSONArray array = JSONArray.parseArray(LockUtils.toString(vo.getResult()));
    		
    		if(array == null || array.isEmpty() || array.size() == 0) {
    			log.warn("智能锁事件推送处理-->锁开门事件 result is null ={}",vo.getResult());
    			return;
    		}
    		
    		List<OpenRecordVO> orList = new ArrayList<>();
    		array.forEach(a->{
    			OpenRecordVO record = JSONObject.parseObject(a.toString(),OpenRecordVO.class);
    			orList.add(record);
    		});
    		
    		
    		if(CollectionUtils.isEmpty(orList)) {
    			log.warn("智能锁事件推送处理-->锁开门事件,result未找到设备");
    			return;
    		}
    		
    		
    		List<String> snList = orList.stream().map(OpenRecordVO::getSn).collect(Collectors.toList());
    		
    		Map<String, List<OpenRecordVO>> snMap = orList.stream().collect(Collectors.groupingBy(OpenRecordVO::getSn));
    		
    		List<SmartLock> lockList = smartLockRepository.findBySnIn(snList);
    		
    		if(CollectionUtils.isEmpty(lockList)) {
    			log.warn("智能锁事件推送处理-->锁开门事件,数据库未找到设备");
    			return;
    		}
    		
    		
    		
    		List<LockOpenLog> logList = new ArrayList<>();
    		for (SmartLock lock : lockList) {
    			List<OpenRecordVO> records = snMap.get(lock.getSn());
    			
    			if(CollectionUtils.isEmpty(records)) {
    				log.warn("智能锁事件推送处理-->锁开门事件,未找到对应的设备 = {}",lock.getSn());
    				return;
    			}
    			
    			
    			OpenRecordVO record = records.get(0);
    			
    			LockOpenLog lockOpenLog = new LockOpenLog();
    			lockOpenLog.setLockId(lock.getId());
    			lockOpenLog.setHouseId(lock.getHouseId());
    			lockOpenLog.setOpenMode(record.getPassType());
    			lockOpenLog.setOpenType(1);//开门类型：0未知 1外开门 2内开门
    			lockOpenLog.setBuildName(lock.getBuildName());
    			lockOpenLog.setCommunityName(lock.getCommunityName());
    			lockOpenLog.setUnitName(lock.getUnitName());
    			lockOpenLog.setMatchUserName(lock.getMatchUserName());
    			lockOpenLog.setRoomNumber(lock.getRoomNumber());
    			lockOpenLog.setOpenTime(new Timestamp(record.getOpenTime()));
    			lockOpenLog.setUserProperty(0);//开门人性质：0未知 1承租人 2同住人
    			
    			//次数密码,减去
    			if(record.getPassType() == 5) {
    				SmartLockPwd pwd = smartLockPwdRepository.findByLockIdAndPwdIndex(lock.getId(), record.getPassId());
    				
    				if(pwd != null) {
    					Integer times = pwd.getTimes() <=0? 0: pwd.getTimes() - 1;
    					pwd.setTimes(times);
    					smartLockPwdRepository.save(pwd);
    				}else{
    					// 检测是否为临时密码, 临时密码索引默认且固定为50
    					if(record.getPassId() != null && record.getPassId() == 50){
    						LockHouseSetting lockHouseSetting = lockHouseSettingRepository.findByLockId(lock.getId());
    						Integer times = lockHouseSetting.getTimes() <= 0?0:lockHouseSetting.getTimes() - 1;
    						lockHouseSetting.setTimes(times);
    						lockHouseSettingRepository.save(lockHouseSetting);
    					}
    				}
    			}
    			
    			
    			//0普通密码 5次数密码
    			if(record.getPassType() == 0  || record.getPassType() == 5) {
    				smartLockPwd(lockOpenLog,record.getPassId(),record.getSn(),lock.getMatchUserId());
    			}else if(record.getPassType() == 1) { //1动态密码 
    			}else if(record.getPassType() == 11) {  //11普通卡 
    				smartLockCard(lockOpenLog,record.getPassId(),record.getSn(),lock.getMatchUserId());
    			}else if(record.getPassType() == 21) { //21指纹
    				smartLockFingerprint(lockOpenLog,record.getPassId(),record.getSn());
    			}
    			
    			if(record.getPassId() < 3000){
    				logList.add(lockOpenLog);
    			}else{
    				log.error("软库数据异常，过滤开门记录, passId", record.getPassId());
    			}
    		}
    		lockOpenLogRepository.saveAll(logList);
    	}catch(Exception e) {
    		log.error("锁开门事件处理异常" + e.getMessage(),e);
    	}
    }

	/**
	 * 密码开门记录
	 */
	private void smartLockPwd(LockOpenLog lock, Integer passId, String sn, String matchUserId) {

		List<Map<String, Object>> lockAuthList = jdbcTemplate.queryForList(authSql, lock.getLockId(), passId);

		if (CollectionUtils.isEmpty(lockAuthList)) {
			log.warn("智能锁事件推送处理-->密码锁开门事件,未找到相关开门人信息 sn={},lockId={},passId={}", sn, lock.getLockId(), passId);
			return;
		}
		Map<String, Object> authMap = lockAuthList.get(0);
		Long lockAuthId = Long.parseLong(authMap.get("lockAuthId").toString());
		String userId = authMap.get("userId").toString();
		if (matchUserId != null && matchUserId.equals(userId)) {
			lock.setUserProperty(1);
		} else {
			lock.setUserProperty(2);
		}
		String userName = authMap.get("userName").toString();
		lock.setLockAuditId(lockAuthId);
		lock.setOpenUserName(userName);
	}

	/**
	 * 指纹开门记录
	 */
	private void smartLockFingerprint(LockOpenLog lock, Integer passId, String sn) {

	}

	/**
	 * 卡开门记录
	 */
	public void smartLockCard(LockOpenLog lock, Integer passId, String sn, String matchUserId) {

		List<Map<String, Object>> lockAuthList = jdbcTemplate.queryForList(cardSql, lock.getLockId(), passId);
		if (CollectionUtils.isEmpty(lockAuthList)) {
			log.warn("智能锁事件推送处理-->卡开门事件,未找到相关开门人信息 sn={},lockId={},passId={}", sn, lock.getLockId(), passId);
			return;
		}
		Map<String, Object> authMap = lockAuthList.get(0);
		Long lockAuthId = Long.parseLong(authMap.get("lockAuthId").toString());
		String userId = authMap.get("userId").toString();
		if (matchUserId != null && matchUserId.equals(userId)) {
			lock.setUserProperty(1);
		} else {
			lock.setUserProperty(2);
		}
		String userName = authMap.get("userName").toString();
		lock.setLockAuditId(lockAuthId);
		lock.setOpenUserName(userName);
	}

	/**
	 * 锁低电量事件
	 * 
	 * @param vo
	 */
	public void lowBatteryCallBack(LockCallBackVO vo) {
		log.info("智能锁事件推送处理-->锁低电量事件 vo={}", vo.toString());
		try {

			JSONArray array = JSONArray.parseArray(LockUtils.toString(vo.getResult()));

			if (array == null || array.isEmpty() || array.size() == 0) {
				log.warn("智能锁事件推送处理-->锁低电量事件 result is null ={}", vo.getResult());
				return;
			}

			List<String> snList = new ArrayList<>();
			array.forEach(a -> {
				JSONObject jo = JSONObject.parseObject(a.toString());
				snList.add(jo.getString("sn"));
			});

			if (CollectionUtils.isEmpty(snList)) {
				log.warn("智能锁事件推送处理-->锁低电量事件, result未找到设备");
				return;
			}

			List<SmartLock> lockList = smartLockRepository.findBySnIn(snList);

			if (CollectionUtils.isEmpty(lockList)) {
				log.warn("智能锁事件推送处理-->锁低电量事件, 数据库未找到设备信息");
				return;
			}

			lockList.forEach(l -> {
				for (int i = 0; i < array.size(); i++) {
					JSONObject jo = JSONObject.parseObject(array.get(i).toString());
					if (l.getSn().equals(jo.getString("sn"))) {
						Integer electric = jo.getInteger("electric");
						l.setElectricQuantity(electric);
						break;
					}
				}
			});
			smartLockRepository.saveAll(lockList);
			Date date = new Date();
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
			String today = formatter.format(date);
			lockList.forEach(l -> {
				// 查询是否设置低电量告警
				LockHouseSetting lockHouseSetting = lockHouseSettingRepository.findByLockId(l.getId());
				// 已开启告警，并当前设备电量小于告警电量时，处理低电量告警
				if (lockHouseSetting == null || lockHouseSetting.getLowPowerStatus() == null
						|| lockHouseSetting.getLowPowerStatus() == 0 || lockHouseSetting.getLowPowerValue() == null
						|| lockHouseSetting.getLowPowerValue() == 0
						|| l.getElectricQuantity() > lockHouseSetting.getLowPowerValue()) {
					log.warn("智能锁事件推送处理-->锁低电量事件, 不符合低电量告警要求, sn={}", l.getSn());
					return;
				}

				BacklogItem log = backlogItemRepository.findByHouseIdAndType(l.getHouseId(),
						BacklogItemTypeEnum.LOCK_LOW_BATTERY.getValue(), today);

				if (log != null) {
					return;
				}

				String content = l.getCommunityName() + l.getUnitName() + l.getBuildName() + l.getRoomNumber();
				// 待办事项
				BacklogItem item = new BacklogItem();
				item.setHouseId(l.getHouseId());
				item.setOrgId(l.getOrgId());
				item.setTitle("门锁低电量告警");
				item.setContent(content);
				item.setBusinessStatus("门锁低电量告警");
				item.setType(BacklogItemTypeEnum.LOCK_LOW_BATTERY.getValue());
				item.setHandleStatus(0);
				item.setMatchUserId(l.getMatchUserId());
				if (!StringUtils.isEmpty(l.getMatchUserId())){
					AppUser appUsers = appUserRepository.findByIdOrEnterpriseUserId(l.getMatchUserId(), l.getMatchUserId());
					if (appUsers != null ){
						item.setPhone(appUsers.getPhone());
					}

				}else {
					List<CommunityHouseUser> communityHouseUserList = communityHouseUserRepository.findByCommunityHouseIdAndStatusAndType(l.getHouseId(), 1, 1);
					if (communityHouseUserList != null && communityHouseUserList.size() > 0) {
						item.setMatchUserId(communityHouseUserList.get(0).getUserId());//承租人ID
						item.setPhone(communityHouseUserList.get(0).getMobile());//电话
					}
				}
				item.setCreateTime(date);
				backlogItemRepository.save(item);
				//门锁低电量待办事项告警
				BacklogItemBattery battery = new BacklogItemBattery();
				battery.setBacklogItemId(item.getId());
				battery.setLockId(l.getId());
				battery.setMatchUserId(l.getMatchUserId());
				backlogItemBatteryRepository.save(battery);
				
				//低电量告警记录
				LockAlarm lockAlarm = new LockAlarm();
				lockAlarm.setAlarmTime(date);
				lockAlarm.setAlarmType(LockAlarmTypeEnum.LOW.getValue());
				lockAlarm.setElectric(l.getElectricQuantity());
				lockAlarm.setLockId(l.getId());
				lockAlarm.setSn(l.getSn());
				lockAlarm.setHouseId(l.getHouseId());
				lockAlarmRepository.save(lockAlarm);
			});

		} catch (Exception e) {
			log.error("锁低电量事件处理异常" + e.getMessage(), e);
		}
	}

}
